import { _decorator, Component, Node, AudioClip, AudioSource, BoxCollider2D, Collider2D, Contact2DType, Sprite, toDegree, sp, Vec2 } from 'cc';
import { Battle } from '../../Battle';
import { BuffHolder } from '../../Buff';
import { EnDynamicLineType } from '../../Common/const/EnCommon';
import { EnEvent } from '../../Common/const/EnEvent';
import { GameAPI } from '../../Common/GameAPI';
import { Eletric } from '../../Eletric';
import { Enum_AudioClip, Enum_ColliderGroup, Enum_PlayerButtleTag } from '../../Enum';
import { Fire } from '../../Fire';
import { Frozen } from '../../Frozen';
import { Globals } from '../../Globals';
import { IceBlock } from '../../IceBlock';
import { KnifeItem } from '../../KnifeItem';
import { Player } from '../../Player/Player';
import { Player_Buttle } from '../../Player/Player_Buttle';
import { ResourcesUtil } from '../../ResourcesUtil';
import { Util } from '../../Util';
import { RedBlinkEffect } from '../RedBlinkEffect';
import { MainTowerController } from '../Tower/MainTowerController';
import { EnemyFrameController } from './EnemyFrameController';
const { ccclass, property } = _decorator;

export enum EnemyFrameAnimType {
    Idle,
    Attack,
    Run,
    Die,
    Hit,
}

export class EnemyFrameInfo {
    public rootPath: string = "";
    public startIndex: number = 0;
    public endIndex: number = 1;
    public frameName: string = "";
    public animType: EnemyFrameAnimType = EnemyFrameAnimType.Idle;
    public speed: number = 0.02;
    public isLoop: boolean = false;
}

@ccclass('EnemyController')
export class EnemyController extends Component {

    @property(Node)
    public bodyNode: Node = null;
    @property(Node)
    public animNode: Node = null;

    public _AttackAudio: AudioClip = null;

    public curAttackInterval: number = 1;
    public attackInterval: number = 1.5;
    // 生命
    public hp: number = 10;
    // 总生命
    public totalHP: number = 10;
    // 攻击力
    public hurt: number = 10;
    // 经验
    public exp: number = 10;
    public _audioSound: AudioSource;
    // 速度
    public _speed: number = 1;
    // 移动方向
    public _moveDirection: number = 0;
    // 是否移动
    public _isMoveing: boolean = false;
    public _buffHolder = new BuffHolder(); //buff
    //是否在攻击
    public _isAttack: boolean = false;
    public _enemyFrameController: EnemyFrameController = null;
    public bodySprite: Sprite;

    public frameInfoList: Array<EnemyFrameInfo> = [];
    public curAnimInfo: EnemyFrameInfo;

    private isColliderTree: boolean = false;

    public isDie: boolean = false;

    public isBoss: boolean = false;
    private isInitUpdateHp: boolean = false;

    public isAttackPlayer: boolean = false;
    private redBlinkEffect: RedBlinkEffect;
    private isUpdateMoveDirection: boolean = false;
    private isColliderMainTower: boolean = false;

    async onLoad(): Promise<void> {
        // 音频
        this._audioSound = this.node.getComponent(AudioSource);
        this._AttackAudio = await ResourcesUtil.loadAudioClip(Enum_AudioClip.attack);
        this.bodySprite = this.animNode.getComponent(Sprite);
        this.bodySprite.spriteFrame = null;
        this.redBlinkEffect = this.node.getComponent(RedBlinkEffect);
    }

    onEnable(): void {
        if (this._enemyFrameController == null) {
            this._enemyFrameController = this.animNode.getComponent(EnemyFrameController);
            this._enemyFrameController.completeListener = this.OnCompleteListener.bind(this);
        }
        this.node.getComponent(BoxCollider2D).on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        this.node.getComponent(BoxCollider2D).on(Contact2DType.END_CONTACT, this.onEndContact, this);

        this._isMoveing = true;
        this._isAttack = false;
        this.isDie = false;
        this.isUpdateMoveDirection = false;
        // buff定义的回调
        this._buffHolder.onCallBack((uid: number, value: number, color: string) => {
            this.Injured(value, color)
        });
        this.onChildInit();
        this.PlayFrameAnim(EnemyFrameAnimType.Run);
    }

    onChildInit() {

    }

    onDisable(): void {
        this.isDie = true;
        this.node.getComponent(BoxCollider2D).off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        this.node.getComponent(BoxCollider2D).off(Contact2DType.END_CONTACT, this.onEndContact, this);
    }

    AttackedPlayer() {
        if (!this.isDie && this.curAnimInfo.animType == EnemyFrameAnimType.Run) {
            this.PlayFrameAnim(EnemyFrameAnimType.Idle);
        }
        this.isAttackPlayer = true;
    }

    SetAttackPlayerState() {
        if (this.isBoss) {
            const playerWorldPos = Battle.playerNode.getWorldPosition();
            const distance = Vec2.distance(this.node.getWorldPosition(), playerWorldPos);
            if (this.isAttackPlayer) {
                if (distance > 120) {
                    //超出boss攻击范围
                    if (!this.isColliderTree) {
                        this._isAttack = false;
                    }
                    this.isAttackPlayer = false;
                }
                else{
                    this._isAttack = true;
                }
            }
            else {
                if (this.isColliderMainTower) {
                    this._isAttack = true;
                }
                else{
                    this._isAttack = false;
                }
            }
        }

    }

    update(deltaTime: number) {
        if (Battle.startGame) {
            this._buffHolder.updated(deltaTime);
            this.SetAttackPlayerState();
            if (this._isAttack) {
                this.curAttackInterval -= deltaTime;
                this.OnAttack(this.curAttackInterval);
                return;
            }
            this.UpdateMoveDirection();
            this.move();
        }
    }

    UpdateCurAnimInfo(type: EnemyFrameAnimType) {
        let animInfo = null;
        for (let index = 0; index < this.frameInfoList.length; index++) {
            const element = this.frameInfoList[index];
            if (element.animType == type) {
                animInfo = element;
                break;
            }
        }
        return animInfo;
    }

    PlayFrameAnim(type: EnemyFrameAnimType) {
        if (this.isDie && type != EnemyFrameAnimType.Die) {
            return;
        }
        if (this.curAnimInfo == null || type != this.curAnimInfo.animType) {
            let animInfo = this.UpdateCurAnimInfo(type);
            if (animInfo) {
                this.curAnimInfo = animInfo;
                this.curAttackInterval = this.attackInterval;
                this._enemyFrameController.UpdateAnimInfo(this.curAnimInfo.speed, this.curAnimInfo.rootPath, this.curAnimInfo.frameName, this.curAnimInfo.startIndex, this.curAnimInfo.endIndex, this.curAnimInfo.isLoop);
            }
        }
    }

    OnCompleteListener(animName) {
        this.curAttackInterval = this.attackInterval;
        this.PlayFrameAnim(EnemyFrameAnimType.Idle);
    }

    OnAttack(interval: number) {
        if (interval <= 0 && !this.isDie) {
            let attackTarget = null;
            if (this.isAttackPlayer) {
                attackTarget = Battle.playerNode;
                this.AttackedPlayerInjured();
            }
            else {
                attackTarget = Battle.MainTowerNode;
                let mainTower: MainTowerController = Battle.MainTowerNode.getComponent(MainTowerController);
                mainTower.UpdateMainTowerHpProgress(this.hurt);
                if (this.isBoss) {
                    GameAPI.FireGEvent(EnEvent.DynamicLineEvent, { type: EnDynamicLineType.MainTowerAttacked });
                }
            }
            if (attackTarget.worldPosition.x >= this.node.worldPosition.x) {
                this.bodyNode.setScale(1, 1);
            } else {
                this.bodyNode.setScale(-1, 1);
            }

            this.PlayFrameAnim(EnemyFrameAnimType.Attack);
            if (this._audioSound && this._AttackAudio) {
                this._audioSound.playOneShot(this._AttackAudio);
            }
        }
    }

    AttackedPlayerInjured() {
        let player: Player = Battle.playerNode.getComponent(Player);
        player.Injured(this.hurt);
    }

    // 受到伤害
    Injured(hurt: number, color: string = "ffffff") {
        if (!this.isInitUpdateHp) {
            this.totalHP = this.hp;
            this.isInitUpdateHp = true;
        }
        this.hp -= hurt;
        if (this.hp <= 0 && !this.isDie) {
            // 血液
            this._isMoveing = false;
            // this._enemyFrameController.UpdateAnimInfo(0.1, "Frame/Enemy/Enemy1/Dying", "0_Skeleton_Dying_", 0, 14);
            this.PlayFrameAnim(EnemyFrameAnimType.Die);
            this.scheduleOnce(this.RemoveEnemyNode.bind(this), 1);
            // this.PlayAnim("die", false);
            this.isDie = true;
            this.OnDieCallback();
            this.hp = 0;
        }
        else {
            // Util.damageTextFun(`${hurt}`, color, this.node.getWorldPosition(), Battle.DamageTextParent);
            this.OnUpdateHP();
        }
        if (this.redBlinkEffect) {
            this.redBlinkEffect.startBlink();
        }
    }

    OnUpdateHP() {

    }

    OnDieCallback() {

    }

    RemoveEnemyNode() {
        Battle.playerNode.getComponent(Player).addExp(this.exp, this.node, this.isBoss);
        this.bodyNode.active = false;
        let shadow = this.bodyNode.parent.getChildByName("shadow");
        if (shadow) {
            shadow.active = false
        }
        let myThis = this;
        this.scheduleOnce(function () {
            myThis.node.destroy();
        }.bind(this), 0.1);
    }

    UpdateMoveDirection() {
        if (!Battle.MainTowerNode || !Battle.MainTowerNode.isValid) {
            return;
        }
        if (this.isAttackPlayer) {
            const deltaX = Battle.playerNode.worldPosition.x - this.node.worldPosition.x;
            const deltaY = Battle.playerNode.worldPosition.y - this.node.worldPosition.y;
            this._moveDirection = Math.atan2(deltaY, deltaX)  //计算出夹角，改变移动方向
        }
        else {
            const deltaX = Battle.MainTowerNode.worldPosition.x - this.node.worldPosition.x;
            const deltaY = Battle.MainTowerNode.worldPosition.y - this.node.worldPosition.y;
            this._moveDirection = Math.atan2(deltaY, deltaX)  //计算出夹角，改变移动方向
        }
    }

    // 敌人移动函数
    move() {
        if (this.isAttackPlayer) {
            // const degree = toDegree(this._moveDirection); //把移动弧度转为角度
            // // 改变角色方向
            // if (degree >= -90 && degree <= 90) {
            //     this.bodyNode.setScale(1, 1);
            // } else {
            //     this.bodyNode.setScale(-1, 1);
            // }
            return;
        }
        if (this._isMoveing) {
            if (this.isDie) {
                this.PlayFrameAnim(EnemyFrameAnimType.Die);
                return;
            }
            // this.PlayAnim("walk", true);
            this.PlayFrameAnim(EnemyFrameAnimType.Run);
            if (this.isColliderTree && !this.isBoss) {
                this._moveDirection += 5;
                // this.isUpdateMoveDirection = true;
            }
            Util.nodeMove(this.node, this._moveDirection, this._speed);
            let targetPosX = 0;
            if (this.isAttackPlayer) {
                targetPosX = Battle.playerNode.position.x;
            }
            else {
                targetPosX = Battle.MainTowerNode.position.x;
            }
            if (this.node.position.x > targetPosX) {
                this.bodyNode.setScale(-1, 1);
            } else {
                this.bodyNode.setScale(1, 1);
            }
        }
    }

    // 碰撞开始回调函数
    onBeginContact(self: Collider2D, other: Collider2D) {
        if (other.group === Enum_ColliderGroup.PLAYER_BULLET) {
            switch (other.tag) {
                // 普通子弹
                case Enum_PlayerButtleTag.Buttle:
                    // 子弹消失
                    Globals.putNode(other.node);
                    this.Injured(other.getComponent(Player_Buttle).hurt);
                    break;
                // 刀子攻击
                case Enum_PlayerButtleTag.Knife:
                    this.Injured(other.getComponent(KnifeItem).hurt);
                    //播放音效
                    break;
                // 火焰攻击
                case Enum_PlayerButtleTag.Fire:
                    this.Injured(other.getComponent(Fire).hurt);
                    // 给个buff
                    this._buffHolder.Add(0, "FFAB96", other.getComponent(Fire).hurt, 3, 1)
                    break;
                // 闪电攻击
                case Enum_PlayerButtleTag.Eletric:
                    this.onEletric(other);
                    break;
                // 冰冻攻击
                case Enum_PlayerButtleTag.Frozen:
                    this.onFrozen(self, other);
                    //播放音效
                    // 给个buff
                    this._buffHolder.Add(1, "52BAFF", other.getComponent(Frozen).hurt, other.getComponent(Frozen).duration, 1)
                    break;
                // 冰块
                case Enum_PlayerButtleTag.Ice:
                    // 给个buff
                    this._buffHolder.Add(1, "52BAFF", other.getComponent(IceBlock).hurt, 2, 1)
                    //播放音效
                    break;
                // 动感光波
                case Enum_PlayerButtleTag.LightWave:
                    this.Injured(999);
                default:
                    break;
            }
        }
        else if (other.group === Enum_ColliderGroup.MAIN_TOWER) {
            this._isAttack = true;
            this.curAttackInterval = this.attackInterval;
            this.OnAttack(0);
            this.isColliderTree = true;
            this.isColliderMainTower = true;
        }
        else if (other.group === Enum_ColliderGroup.TREE || other.group === Enum_ColliderGroup.WALL) {
            // console.log("碰到树了");
            this.isColliderTree = true;
        }
    }
    // 碰撞结束回调
    onEndContact(self: Collider2D, other: Collider2D) {
        if (other.group === Enum_ColliderGroup.MAIN_TOWER) {
            this._isAttack = false;
            this.isColliderTree = false;
            this.isUpdateMoveDirection = false;
            this.isColliderMainTower = false;
        }
        else if (other.group === Enum_ColliderGroup.TREE || other.group === Enum_ColliderGroup.WALL) {
            this.isColliderTree = false;
            this.isUpdateMoveDirection = false;
        }
    }

    // 被闪电攻击
    onEletric(other: Collider2D) {
        this.Injured(other.getComponent(Eletric).hurt);
    }
    // 被冰冻攻击
    onFrozen(self: Collider2D, other: Collider2D) {
        this.scheduleOnce(() => {
            // 恢复移动与动画
            this._isMoveing = true;
            this.Injured(other.getComponent(Frozen).hurt);
        }, other.getComponent(Frozen).duration)
    }
}


